package com.wzh.navcode.strategy;

import cn.hutool.http.HttpStatus;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
import com.github.rholder.retry.RetryerBuilder;
import com.github.rholder.retry.StopStrategies;
import com.wzh.navcode.domain.entity.HotData;
import com.wzh.navcode.domain.vo.BilibiliHotTopic;
import com.wzh.navcode.service.CrawlStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import cn.hutool.json.JSONObject;

/**
 * @Author: wangzh
 * @Version: 1.0
 * @Description: bilibili 爬虫策略
 */
@Service("bilibiliStrategy")
@Slf4j
public class BilibiliCrawlStrategy implements CrawlStrategy {
    private static final String BILIBILI_URL = "https://api.it8.com.cn/bilibili";
    /**
     * 超时时间
     */
    private static final int TIMEOUT = 5000;

    @Override
    public List<HotData> crawl() {
        try {
            String json = fetchDataWithRetry();
            return parseAndConvertData(json);
        } catch (Exception e) {
            log.error("爬取b站数据失败:{}", e.getMessage());
            return new ArrayList<>();
        }
    }

    private String fetchDataWithRetry() throws ExecutionException, RetryException {
        Callable<String> callable = () -> {
            String json = HttpUtil.createGet(BILIBILI_URL)
                    .timeout(TIMEOUT)
                    .execute()
                    .body();
            JSONObject jsonObj = JSONUtil.parseObj(json);
            int code = jsonObj.getInt("code");
            if (HttpStatus.HTTP_OK != code) {
                throw new RuntimeException("请求失败，状态码：" + code);
            }
            return json;
        };
        Retryer<String> retryer = RetryerBuilder.<String>newBuilder()
                .retryIfException()
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .build();
        return retryer.call(callable);
    }

    private List<HotData> parseAndConvertData(String json) {
        JSONObject jsonObj = JSONUtil.parseObj(json);
        Object dataObj = jsonObj.get("data");
        if (dataObj == null) {
            return new ArrayList<>();
        }
        List<BilibiliHotTopic> list = JSONUtil.parseArray(dataObj)
                .toList(BilibiliHotTopic.class);
        return convertToHotData(list);
    }

    private List<HotData> convertToHotData(List<BilibiliHotTopic> list) {
        List<HotData> hotDataList = new ArrayList<>();
        String formattedTime = "今天" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm"));
        list.stream()
            .sorted(Comparator.comparing(BilibiliHotTopic::getHot).reversed())
            .forEach(hotTopic -> {
                hotDataList.add(HotData.builder()
                        .title(hotTopic.getTitle())
                        .url(hotTopic.getUrl())
                        .hotValue(formatHotValue(hotTopic.getHot()))
                        .crawlTime(formattedTime)
                        .platform("b站")
                        .build());
            });
        return hotDataList.subList(0,8);
    }

    private String formatHotValue(double hot) {
        if (hot < 10000) {
            return String.format("%.1f", hot);
        }
        return String.format("%.1f万", hot / 10000.0);
    }
}
